C/C++:sizeof数组与指针 |
您所在的位置:网站首页 › c 查看指针类型 › C/C++:sizeof数组与指针 |
C/C++:sizeof数组与指针
在C/C++中使用sizeof对数组和指针所得的结果是不一样的。 [例1] #include #include #define SAFE_FREE(p) {free(p);p=NULL;} int main() { char arr[20]; char *p = (char *)malloc(sizeof(char) * 20); printf("sizeof arr :%d\n", sizeof(arr)); printf("sizeof p :%d\n", sizeof(p)); SAFE_FREE(p); return 0; }输出: [test1280@localhost 20170416]$ ./main sizeof arr :20 sizeof p :4sizeof一个变量得到这个变量所占用的字节数。 使用sizeof对一个数组操作(sizeof是一个操作符,而不是一个函数),得到的是这个数组占用的内存字节数。 有可能会这么想:使用sizeof对一个指针操作,得到的将会是指针指向的空间所占用的字节数? 并不是! 指针是啥?指针是个变量,既然是变量,那你sizeof一个指针变量,得到的结果当然是这个指针变量占据的字节数。 一个指针变量是做什么用的?要标识一个地址,这个地址在整个计算机内是全局唯一的。 如果计算机最多寻址4G有32地址线,你用16位的一个变量能唯一标识吗?显然不可以。 一个指针变量的大小不仅和计算机本身硬件、操作系统有关,而且还和你的编译器有关系。 完全可能是在64位机上使用编译器编译出来的一个指针变量占据的大小是4字节。 注:下面所进行的所有试验都是基于以下环境: [test1280@localhost 20170416]$ uname -a Linux localhost.localdomain 2.6.32-431.el6.i686 #1 SMP Fri Nov 22 00:26:36 UTC 2013 i686 i686 i386 GNU/Linux [test1280@localhost 20170416]$ gcc --version gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-18) Copyright (C) 2010 Free Software Foundation, Inc.例1说明: 数组名和指针变量还是有区别的,虽然他们都可以通过[]或者*来访问变量/数组。 对一个指针变量用sizeof操作,得到的结果永远是指针变量本身的大小,而不是指针变量指向的空间的大小。 [例2] #include #include #define SAFE_FREE(p) {free(p);p=NULL;} void foo(char arr[], char *p) { printf("sizeof arr :%d\n", sizeof(arr)); printf("sizeof p :%d\n", sizeof(p)); } int main() { char arr[20]; char *p = (char *)malloc(sizeof(char) * 20); foo(arr, p); SAFE_FREE(p); return 0; }输出结果为: [test1280@localhost 20170416]$ ./main sizeof arr :4 sizeof p :4结论: 数组在进行函数调用作为参数被传递时,在被调用函数内部其退化为指针,使用sizeof等价于对一个指针变量进行sizeof,大小为一个指针变量所占的内存空间。 通常我们可以看到,一个形参是数组类型的,或者是指针类型的,都包含了另一个形参,是个整型值,用来标识数组类型(指针类型)的大小的,因为在被调用函数内部不知道其大小呀! 下面介绍下sizeof。 sizeof是一个操作符,而不是一个函数,其返回值是size_t类型。 sizeof是编译时进行的,也就是说,其值的大小,是在运行之前就已经决定好的,不像函数调用,是在运行期间决定的。 sizeof的对象可以是一个类型,也可以是一个变量。 #include #include int main() { printf("%d\n", sizeof(char)); printf("%d\n", sizeof(int)); char c; int i; printf("%d\n", sizeof(c)); printf("%d\n", sizeof(i)); printf("%d\n", sizeof c); printf("%d\n", sizeof i); return 0; }编译运行都OK。 注意下面的程序: #include #include int main() { printf("%d\n", sizeof char); printf("%d\n", sizeof int); return 0; }编译报错: [test1280@localhost 20170416]$ gcc -o main main.c -Wall main.c: In function ‘main’: main.c:6: error: expected expression before ‘char’ main.c:7: error: expected expression before ‘int’总结: 使用sizeof有三种正确方式: sizeof(type_name); sizeof(var); sizeof var; 但是sizeof type_name是错误的。 建议: 使用sizeof时,统一都加上括号吧。 [例3] #include #include int main() { int n = 0; printf("%d\n", sizeof(n=100)); printf("%d\n", n); return 0; }输出: [test1280@localhost 20170416]$ !g gcc -o main main.c -Wall [test1280@localhost 20170416]$ ./main 4 0为什么输出是0呢?关键在于,sizeof是在编译阶段就已经确定了的,表达式: n = 100 这是一个赋值表达式,操作符=返回左操作数的类型,也就是int。 所以,在编译完成之后,运行之前,实际上就是等价于输出sizeof(int)。 由于sizeof不能被编译成机器码,所以sizeof作用范围内,也就是()里面的内容也不能被编译,而是被替换成类型。 [例4] #include #include char char_f(){return 'a';} int int_f(){return 0;} double double_f(){return 0;} void void_f(){} int main() { printf("%d\n", sizeof(char_f())); printf("%d\n", sizeof(int_f())); printf("%d\n", sizeof(double_f())); printf("%d\n", sizeof(void_f())); printf("\n"); printf("%d\n", sizeof(void)); printf("\n"); printf("%d\n", sizeof(char_f)); printf("%d\n", sizeof(int_f)); printf("%d\n", sizeof(double_f)); printf("%d\n", sizeof(void_f)); return 0; }输出: [test1280@localhost 20170416]$ !g gcc -o main main.c -Wall [test1280@localhost 20170416]$ ./main 1 4 8 1 1 1 1 1 1 [test1280@localhost 20170416]$首先前四个比较好理解,sizeof返回的是各个函数的返回值的类型的大小; 对于void来说,使用sizeof得到的是1; 末尾的四个1我暂时无法解释,留待日后解释,或者有朋友来帮我解释下~谢谢啦~ (注:函数名仅仅是个符号,代表一个地址,应该也是4,为什么是1?) [例5] #include #include int main() { double* (*a)[3][6]; printf("%d\n", sizeof(a)); //4 printf("%d\n", sizeof(*a)); //3*6*4 printf("%d\n", sizeof(**a)); //6*4 printf("%d\n", sizeof(***a)); //4 printf("%d\n", sizeof(****a)); //8 char arr[5][8]; printf("%d\n", sizeof(*arr)); //8 return 0; }输出: [test1280@localhost 20170416]$ !g gcc -o main main.c [test1280@localhost 20170416]$ ./main 4 72 24 4 8 8对例5的解释: a是啥?a首先是一个指针,类似于int (*a); 所以,sizeof(a)等同于sizeof(char *),也就是4(可能是8); 这个指针指向一个什么类型的数据呢? 比对int (a),指向一个int类型的数据,那么也就不难理解,这里的a指向一个double*[3][6]类型的数据; 所以*a就代表了这样的一个数据实体,里面每一个元素都是一个指针,指向一个double对象,共有这样的指针多少个呢?3*6=18个,每个指针多大呢?4字节,所以结果就是3*6*4=72; **a从含义上来说等价于*arr; arr是一个指向数组的指针,是数组级别的; *arr是一个指向数组中某一行的指针,是行级别的; **arr是一个指向数组中某一个元素的指针,是元素级别的。 而sizeof(arr)结果是对行所有元素求大小,即一行的元素数量每个元素的大小,所以sizeof(*arr)结果是8*1=8; 回想这里的**arr,结果自然就是6*4=24; ***arr上面已经说了,这是一个具体的对象了,这时具体的对象是一个double类型指针,所以是4(或者8); ****arr是什么类型的呢?是一个double类型,结果就是8。 基本上就是这样理解的。 额,最后来看个简单的小程序: [例6] #include #include #define ARRAY_SIZE(arr, type_name) (sizeof(arr)/sizeof(type_name)) int main() { char arr[] = "abcdef"; char *p = arr; printf("%d\n", sizeof(arr)); //7 printf("%d\n", sizeof(p)); //4 // 获得数组大小(以元素为单位)的方式 int array[] = {1, 2, 3, 4, 5, 6}; printf("%d\n", ARRAY_SIZE(array, int)); char s[2048] = "abcdefgh"; // 输出2048,初始化是初始化,已经确定了数组大小的情况下不会影响数组的大小,并不是9 printf("%d\n", sizeof(s)); return 0; }输出: [test1280@localhost 20170416]$ gcc -o main main.c [test1280@localhost 20170416]$ ./main 7 4 6 2048值得注意的是使用一个宏来求一个数组大小的这种方式。 但是也是有前提的,必须是在可识别数组大小(sizeof 数组正确时)才是成立的,毕竟宏也仅仅是做一个替换。 参考来源: 1.http://blog.csdn.net/luguifang2011/article/details/39988627 2.http://blog.csdn.net/kangroger/article/details/20653255 3.http://www.cnblogs.com/qingergege/p/5943764.html |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |